<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JSON格式化查看器</title>
<!--    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">-->
    <link rel="stylesheet" href="/css/all.min.css">
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }

        body {
            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
            min-height: 100vh;
            padding: 20px;
            display: flex;
            justify-content: center;
            align-items: center;
            color: #333;
        }

        .container {
            width: 100%;
            max-width: 1200px;
            background: rgba(255, 255, 255, 0.95);
            border-radius: 15px;
            box-shadow: 0 15px 35px rgba(0, 0, 0, 0.3);
            overflow: hidden;
        }

        header {
            background: linear-gradient(90deg, #2c3e50, #4a6491);
            color: white;
            padding: 20px;
            text-align: center;
            position: relative;
        }

        h1 {
            font-size: 2.2rem;
            margin-bottom: 10px;
            font-weight: 600;
        }

        .subtitle {
            font-size: 1.1rem;
            opacity: 0.9;
            margin-bottom: 15px;
        }

        .header-actions {
            display: flex;
            justify-content: center;
            gap: 15px;
            margin-top: 15px;
        }

        .btn {
            background: #3498db;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 50px;
            cursor: pointer;
            font-weight: 600;
            transition: all 0.3s;
            display: flex;
            align-items: center;
            gap: 8px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
        }

        .btn:hover {
            transform: translateY(-3px);
            box-shadow: 0 6px 12px rgba(0, 0, 0, 0.25);
        }

        .btn.btn-success {
            background: #2ecc71;
        }

        .btn.btn-warning {
            background: #e67e22;
        }

        .btn.btn-danger {
            background: #e74c3c;
        }

        .content {
            display: flex;
            flex-wrap: wrap;
            min-height: 500px;
        }

        .input-section, .output-section {
            flex: 1;
            min-width: 300px;
            padding: 25px;
            display: flex;
            flex-direction: column;
        }

        .input-section {
            background: #f8f9fa;
            border-right: 1px solid #eaeaea;
        }

        .section-title {
            font-size: 1.4rem;
            margin-bottom: 15px;
            color: #2c3e50;
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .section-title i {
            color: #3498db;
        }

        textarea {
            width: 100%;
            height: 300px;
            padding: 15px;
            border: 1px solid #ddd;
            border-radius: 10px;
            font-family: 'Courier New', monospace;
            font-size: 1rem;
            resize: vertical;
            margin-bottom: 20px;
            box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.05);
        }

        textarea:focus {
            outline: none;
            border-color: #3498db;
            box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2);
        }

        .output-section {
            position: relative;
        }

        .json-container {
            flex: 1;
            border: 1px solid #eaeaea;
            border-radius: 10px;
            padding: 20px;
            background: #2c3e50;
            color: #ecf0f1;
            overflow: auto;
            font-family: 'Courier New', monospace;
            position: relative;
            box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.3);
        }

        .json-line {
            margin-left: 20px;
            position: relative;
            line-height: 1.6;
        }

        .json-key {
            color: #3498db;
        }

        .json-string {
            color: #2ecc71;
        }

        .json-number {
            color: #e67e22;
        }

        .json-boolean {
            color: #9b59b6;
        }

        .json-null {
            color: #e74c3c;
        }

        .json-bracket {
            color: #f1c40f;
        }

        .toggle {
            position: absolute;
            left: -15px;
            top: 3px;
            cursor: pointer;
            color: #7f8c8d;
            font-size: 0.9rem;
        }

        .collapsed > .json-children {
            display: none;
        }

        .collapsed::after {
            content: " ...";
            color: #7f8c8d;
        }

        .copy-notification {
            position: absolute;
            top: 20px;
            right: 20px;
            background: rgba(46, 204, 113, 0.9);
            color: white;
            padding: 10px 20px;
            border-radius: 5px;
            font-weight: 600;
            display: none;
            animation: fadeOut 2s ease-in-out;
        }

        @keyframes fadeOut {
            0% { opacity: 1; }
            70% { opacity: 1; }
            100% { opacity: 0; }
        }

        .stats {
            display: flex;
            justify-content: space-between;
            margin-top: 15px;
            background: #e3f2fd;
            padding: 10px 15px;
            border-radius: 8px;
            font-size: 0.9rem;
        }

        .stat-item {
            display: flex;
            flex-direction: column;
            align-items: center;
        }

        .stat-value {
            font-weight: 700;
            font-size: 1.2rem;
            color: #2c3e50;
        }

        .stat-label {
            color: #7f8c8d;
            font-size: 0.8rem;
        }

        .example-json {
            margin-top: 15px;
            background: #e3f2fd;
            padding: 15px;
            border-radius: 10px;
            font-size: 0.9rem;
        }

        .example-title {
            font-weight: 600;
            margin-bottom: 8px;
            color: #2c3e50;
        }

        .example-code {
            font-family: 'Courier New', monospace;
            font-size: 0.85rem;
            color: #3498db;
        }

        footer {
            text-align: center;
            padding: 20px;
            background: #f8f9fa;
            color: #7f8c8d;
            font-size: 0.9rem;
            border-top: 1px solid #eaeaea;
        }

        @media (max-width: 768px) {
            .content {
                flex-direction: column;
            }

            .input-section {
                border-right: none;
                border-bottom: 1px solid #eaeaea;
            }
        }
    </style>
</head>
<body>
<div class="container">
    <header>
        <h1><i class="fas fa-code"></i> JSON格式化查看器</h1>
        <p class="subtitle">格式化、高亮显示并美化您的JSON数据</p>
        <div class="header-actions">
            <button class="btn" id="formatBtn">
                <i class="fas fa-magic"></i> 格式化JSON
            </button>
            <button class="btn btn-success" id="copyBtn">
                <i class="fas fa-copy"></i> 复制结果
            </button>
            <button class="btn btn-warning" id="clearBtn">
                <i class="fas fa-broom"></i> 清除内容
            </button>
            <button class="btn btn-danger" id="exampleBtn">
                <i class="fas fa-lightbulb"></i> 加载示例
            </button>
        </div>
    </header>

    <div class="content">
        <div class="input-section">
            <h2 class="section-title"><i class="fas fa-edit"></i> 输入JSON</h2>
            <textarea id="jsonInput" placeholder='在此粘贴您的JSON数据，例如：{"name": "John", "age": 30, "isStudent": false}'></textarea>

            <div class="example-json">
                <div class="example-title">JSON示例：</div>
                <div class="example-code">
                    {"name": "John Doe", "age": 30, "isStudent": false, "address": {"street": "123 Main St", "city": "Anytown"}, "hobbies": ["reading", "hiking", "coding"]}
                </div>
            </div>
        </div>

        <div class="output-section">
            <h2 class="section-title"><i class="fas fa-eye"></i> 格式化结果</h2>
            <div class="json-container" id="jsonOutput">
                <div class="json-placeholder">
                    <p>JSON格式化结果将显示在这里</p>
                    <p>请点击"格式化JSON"按钮处理您的数据</p>
                </div>
            </div>

            <div id="copyNotification" class="copy-notification">
                <i class="fas fa-check-circle"></i> 已复制到剪贴板！
            </div>

            <div class="stats">
                <div class="stat-item">
                    <span class="stat-value" id="charCount">0</span>
                    <span class="stat-label">字符</span>
                </div>
                <div class="stat-item">
                    <span class="stat-value" id="lineCount">0</span>
                    <span class="stat-label">行数</span>
                </div>
                <div class="stat-item">
                    <span class="stat-value" id="objectCount">0</span>
                    <span class="stat-label">对象</span>
                </div>
                <div class="stat-item">
                    <span class="stat-value" id="arrayCount">0</span>
                    <span class="stat-label">数组</span>
                </div>
            </div>
        </div>
    </div>

    <footer>
        <p>JSON格式化查看器 &copy; 2023 | 使用HTML5、CSS3和JavaScript构建</p>
    </footer>
</div>

<script>
    document.addEventListener('DOMContentLoaded', function() {
        const jsonInput = document.getElementById('jsonInput');
        const jsonOutput = document.getElementById('jsonOutput');
        const formatBtn = document.getElementById('formatBtn');
        const copyBtn = document.getElementById('copyBtn');
        const clearBtn = document.getElementById('clearBtn');
        const exampleBtn = document.getElementById('exampleBtn');
        const copyNotification = document.getElementById('copyNotification');
        const charCount = document.getElementById('charCount');
        const lineCount = document.getElementById('lineCount');
        const objectCount = document.getElementById('objectCount');
        const arrayCount = document.getElementById('arrayCount');

        // 示例JSON数据
        const exampleJson = {
            "name": "John Doe",
            "age": 30,
            "isStudent": false,
            "address": {
                "street": "123 Main St",
                "city": "Anytown",
                "coordinates": {
                    "lat": 12.34,
                    "lng": 56.78
                }
            },
            "hobbies": ["reading", "hiking", "coding"],
            "scores": [100, 95, 88],
            "contact": {
                "email": "john@example.com",
                "phones": [
                    { "type": "home", "number": "555-1234" },
                    { "type": "mobile", "number": "555-5678" }
                ]
            },
            "nullValue": null
        };

        // 按钮事件监听
        formatBtn.addEventListener('click', formatJson);
        copyBtn.addEventListener('click', copyResult);
        clearBtn.addEventListener('click', clearInput);
        exampleBtn.addEventListener('click', loadExample);

        // 初始加载示例
        loadExample();

        // 加载示例JSON
        function loadExample() {
            jsonInput.value = JSON.stringify(exampleJson, null, 2);
            formatJson();
        }

        // 清除输入
        function clearInput() {
            jsonInput.value = '';
            jsonOutput.innerHTML = '<div class="json-placeholder"><p>JSON格式化结果将显示在这里</p><p>请点击"格式化JSON"按钮处理您的数据</p></div>';
            updateStats(0, 0, 0, 0);
        }

        // 格式化JSON
        function formatJson() {
            try {
                const inputText = jsonInput.value.trim();
                if (!inputText) {
                    jsonOutput.innerHTML = '<div class="json-error">请输入JSON数据</div>';
                    return;
                }

                const jsonObj = JSON.parse(inputText);
                const formattedHtml = formatJsonToHtml(jsonObj);
                jsonOutput.innerHTML = formattedHtml;

                // 添加折叠功能
                addCollapseFunctionality();

                // 更新统计信息
                const jsonString = JSON.stringify(jsonObj);
                updateStats(
                    jsonString.length,
                    jsonString.split('\n').length,
                    countObjects(jsonObj),
                    countArrays(jsonObj)
                );

            } catch (error) {
                jsonOutput.innerHTML = `<div class="json-error">JSON解析错误: ${error.message}</div>`;
                updateStats(0, 0, 0, 0);
            }
        }

        // 将JSON对象格式化为HTML
        function formatJsonToHtml(obj, indent = 0, isArray = false) {
            let html = '';
            const indentStr = ' '.repeat(indent * 4);

            if (obj === null) {
                return `<span class="json-null">null</span>`;
            }

            const type = typeof obj;

            if (type === 'string') {
                return `<span class="json-string">"${obj}"</span>`;
            }

            if (type === 'number') {
                return `<span class="json-number">${obj}</span>`;
            }

            if (type === 'boolean') {
                return `<span class="json-boolean">${obj}</span>`;
            }

            if (Array.isArray(obj)) {
                if (obj.length === 0) {
                    return `<span class="json-bracket">[</span><span class="json-bracket">]</span>`;
                }

                html += `<span class="json-bracket">[</span>`;
                html += `<span class="toggle">-</span>`;
                html += `<div class="json-children">`;

                obj.forEach((item, index) => {
                    const comma = index < obj.length - 1 ? '<span class="json-bracket">,</span>' : '';
                    html += `<div class="json-line">${formatJsonToHtml(item, indent + 1, true)}${comma}</div>`;
                });

                html += `</div>`;
                html += `<div class="json-line">${indentStr}<span class="json-bracket">]</span></div>`;

                return html;
            }

            if (type === 'object') {
                const keys = Object.keys(obj);
                if (keys.length === 0) {
                    return `<span class="json-bracket">{</span><span class="json-bracket">}</span>`;
                }

                html += `<span class="json-bracket">{</span>`;
                html += `<span class="toggle">-</span>`;
                html += `<div class="json-children">`;

                keys.forEach((key, index) => {
                    const comma = index < keys.length - 1 ? '<span class="json-bracket">,</span>' : '';
                    const valueHtml = formatJsonToHtml(obj[key], indent + 1);
                    html += `<div class="json-line"><span class="json-key">"${key}"</span>: ${valueHtml}${comma}</div>`;
                });

                html += `</div>`;
                html += `<div class="json-line">${indentStr}<span class="json-bracket">}</span></div>`;

                return html;
            }

            return '';
        }

        // 添加折叠功能
        function addCollapseFunctionality() {
            const toggles = jsonOutput.querySelectorAll('.toggle');
            toggles.forEach(toggle => {
                toggle.addEventListener('click', function() {
                    const children = this.nextElementSibling;
                    if (children) {
                        if (this.textContent === '-') {
                            this.textContent = '+';
                            this.parentElement.classList.add('collapsed');
                        } else {
                            this.textContent = '-';
                            this.parentElement.classList.remove('collapsed');
                        }
                    }
                });
            });
        }

        // 复制结果到剪贴板
        function copyResult() {
            const inputText = jsonInput.value.trim();
            if (!inputText) return;

            try {
                const jsonObj = JSON.parse(inputText);
                const formattedJson = JSON.stringify(jsonObj, null, 2);

                navigator.clipboard.writeText(formattedJson).then(() => {
                    copyNotification.style.display = 'block';
                    setTimeout(() => {
                        copyNotification.style.display = 'none';
                    }, 2000);
                });
            } catch (error) {
                alert(`复制失败: ${error.message}`);
            }
        }

        // 更新统计信息
        function updateStats(chars, lines, objects, arrays) {
            charCount.textContent = chars;
            lineCount.textContent = lines;
            objectCount.textContent = objects;
            arrayCount.textContent = arrays;
        }

        // 计算对象数量
        function countObjects(obj) {
            if (typeof obj !== 'object' || obj === null) return 0;

            let count = Array.isArray(obj) ? 0 : 1;
            for (let key in obj) {
                if (typeof obj[key] === 'object' && obj[key] !== null) {
                    count += countObjects(obj[key]);
                }
            }

            return count;
        }

        // 计算数组数量
        function countArrays(obj) {
            if (typeof obj !== 'object' || obj === null) return 0;

            let count = Array.isArray(obj) ? 1 : 0;
            for (let key in obj) {
                if (typeof obj[key] === 'object' && obj[key] !== null) {
                    count += countArrays(obj[key]);
                }
            }

            return count;
        }
    });
</script>
</body>
</html>
